﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Collections;

namespace Problema1_AbstractFactory_Singleton_ObjectPool
{
    //Aceasta clasa implementeaza : - modelul abstract factory
    //                              - object pool (cand o masina noua de un anumit tip (sedan/mini/coupe) este comandata
    //                                  si nu este gasita pe stoc, atunci se mai produce inca una identica si introdusa
    //                                  pe stoc).
    //                                  Urmatoarea comanda pentru o masina de acelasi tip va primi masina de pe stoc,
    //                                  chiar daca nu are aceleasi optiuni. (Pentru a putea face livrarile mai rapide)
    //                              - singleton (clasa FactoryForPassengerCars_Singleton poate fi instantiata o singura data)
    public class FactoryForPassengerCars_Singleton : Factory
    {
        private static FactoryForPassengerCars_Singleton instance;
        private FactoryForPassengerCars_Singleton() { }
        public static FactoryForPassengerCars_Singleton getSingletonInstance()
        {
             if (instance == null)
             {
                instance = new FactoryForPassengerCars_Singleton();
             }
             return instance;
        }

        Culoare CULOARE;
        Transmisie TRANSMISIE;
        Climatizare CLIMATIZARE;
        Tapiterie TAPITERIE;
        // Maximum Number of objects allowed
        private static int MAX = 3;

        // My collection Pool
        private static readonly Queue sedanSTOC = new Queue(MAX);
        private static readonly Queue miniSTOC = new Queue(MAX);
        private static readonly Queue coupeSTOC = new Queue(MAX);

        public override Masina comandaMasina(int tip, int cul, int trs, int clm, int tap)
        {
            Masina m=null;
            CULOARE = null;
            TRANSMISIE = null;
            CLIMATIZARE = null;
            TAPITERIE = null;

            if (cul==0) CULOARE = new CuloareAlb();
            if (cul==1) CULOARE = new CuloareNegru();
            if (trs == 0) TRANSMISIE = new TransmisieManuala();
            if (trs == 1) TRANSMISIE = new TransmisieAutomata();
            if (clm == 0) CLIMATIZARE = new ClimatizareManuala();
            if (clm == 1) CLIMATIZARE = new ClimatizareAutomata();
            if (tap == 0) TAPITERIE = new TapiterieStofa();
            if (tap == 1) TAPITERIE = new TapiteriePiele();

            if ((tip == 0) && (sedanSTOC.Count > 0))
                m = SedanRetrieveFromPool();
            else
                if (tip==0) m = SedanGetNew();

            if ((tip == 1) && (miniSTOC.Count > 0))
                m = MiniRetrieveFromPool();
            else
                if (tip==1) m = MiniGetNew();

            if ((tip == 2) && (coupeSTOC.Count > 0))
                m = CoupeRetrieveFromPool();
            else
                if (tip==2) m = CoupeGetNew();

            return m;
        }

        protected Masina SedanRetrieveFromPool()
        {
            Masina m;
            m = (MasinaSedan)sedanSTOC.Dequeue();
            //MasinaSedan.COUNTER--;
            return m;
        }
        protected Masina SedanGetNew()
        {
            Masina mComandatDeClient = new MasinaSedan();
            Masina mIdenticPtIntrodusPeStoc = new MasinaSedan();
            
            mComandatDeClient = new MasinaSedan(CULOARE,TRANSMISIE,CLIMATIZARE,TAPITERIE);
            mIdenticPtIntrodusPeStoc = new MasinaSedan(CULOARE, TRANSMISIE, CLIMATIZARE, TAPITERIE);

            if (sedanSTOC.Count<MAX) sedanSTOC.Enqueue(mIdenticPtIntrodusPeStoc);
            return mComandatDeClient;
        }
        protected Masina MiniRetrieveFromPool()
        {
            Masina m;
            m = (MasinaMini)miniSTOC.Dequeue();
            //MasinaMini.COUNTER--;
            return m;
        }
        protected Masina MiniGetNew()
        {
            Masina mComandatDeClient = new MasinaMini();
            Masina mIdenticPtIntrodusPeStoc = new MasinaMini();

            mComandatDeClient = new MasinaMini(CULOARE, TRANSMISIE, CLIMATIZARE, TAPITERIE);
            mIdenticPtIntrodusPeStoc = new MasinaMini(CULOARE, TRANSMISIE, CLIMATIZARE, TAPITERIE);

            if (miniSTOC.Count < MAX) miniSTOC.Enqueue(mIdenticPtIntrodusPeStoc);
            return mComandatDeClient;
        }
        protected Masina CoupeRetrieveFromPool()
        {
            Masina m;
            m = (MasinaCoupe)coupeSTOC.Dequeue();
            //MasinaCoupe.COUNTER--;
            return m;
        }
        protected Masina CoupeGetNew()
        {
            Masina mComandatDeClient = new MasinaCoupe();
            Masina mIdenticPtIntrodusPeStoc = new MasinaMini();

            mComandatDeClient = new MasinaCoupe(CULOARE, TRANSMISIE, CLIMATIZARE, TAPITERIE);
            mIdenticPtIntrodusPeStoc = new MasinaCoupe(CULOARE, TRANSMISIE, CLIMATIZARE, TAPITERIE);

            if (coupeSTOC.Count < MAX) coupeSTOC.Enqueue(mIdenticPtIntrodusPeStoc);
            return mComandatDeClient;
        }
    }
}
